package preprocess;

import java.util.*;

import FlowGraph.*;
import SymbolTable.*;
import FlowGraph.Nodes.*;
import util.Util;
import util.InfoCollector;
import db.ClassData; 

//////////////////////////////////////////////////////////////////////////
//// DEInfoCollector
/**
@author Ivan Jeukens
@version v 0.1 18/10/2002
*/
public class DEInfoCollector implements InfoCollector {

    public DEInfoCollector() {
        _dePorts = new HashMap();
        _deMethod = new LinkedList();
    }

    ///////////////////////////////////////////////////////////////////
    ////                         public methods                    ////

    public void visitFGNode(FlowGraphNode node) {
        if(node.getType() != FlowGraphNode.METHOD_CALL) return;
        MethodCallNode mc = (MethodCallNode) node;

        String mname = mc.getMethodName();
        Class c = mc.getCallerType();
        if(mname != null && c != null && _isDEMethod(mname, mc) &&
               Util.isSubClass(c, ptolemy.domains.de.kernel.DEIOPort.class)) {
            _deMethod.add(node);
        }
    }

    public void visitSTEntry(STEntry entry, FlowGraphNode owner, ClassData info) {
        if(entry instanceof STPortEntry) {
            Class type = entry.getType();
            if(type.equals(ptolemy.domains.de.kernel.DEIOPort.class)) {
                _dePorts.put(entry, info);
            }
        }
    }
    
    public Iterator deMethodIterator() {
        return _deMethod.iterator();
    }

    ///////////////////////////////////////////////////////////////////
    ////                         private methods                   ////

    private boolean _isDEMethod(String mname, MethodCallNode mc) {
        if(mname.equals("delayTo") ||
           mname.equals("getDelayedPorts")) return true;

        if(mname.equals("broadcast")) {
            if(mc.parametersSize() != 2) return false;
            
            if(Util.isSubClass(mc.getParameterType(0), 
                  ptolemy.data.Token.class) &&
               Util.isSubClass(mc.getParameterType(1),
                   double.class)) {
                return true;
            }

            return false;
        }

        if(mname.equals("send")) {
            if(mc.parametersSize() != 3) return false;

            if(Util.isSubClass(mc.getParameterType(0), int.class) &&
               Util.isSubClass(mc.getParameterType(1), 
                   ptolemy.data.Token.class) &&
               Util.isSubClass(mc.getParameterType(2),
                   double.class)) {
                return true;
            }

            return false;
        }
        return false;
    }
    
    public int deMethodSize() {
        return _deMethod.size();
    }

    public int dePortsSize() {
        return _dePorts.size();
    }


    ///////////////////////////////////////////////////////////////////
    ////                       private variables                   ////

    // Um map entre uma entrada de porto e a classinfo relacionada
    private HashMap _dePorts;

    // Lista de nos onde os metodos sao especificos do DE
    private LinkedList _deMethod;
}
